package com.example.io;

import android.Manifest;
import android.app.Activity;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.util.Log;
import android.view.View;
import android.widget.CompoundButton;
import android.widget.Switch;
import android.widget.TextView;

import org.apache.commons.io.FileUtils;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledThreadPoolExecutor;

public class MainActivity extends Activity {

    static {
        System.loadLibrary("native-lib");
    }

    private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
    private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;

    TextView mCpuUsageTv;
    private ArrayList<OneCpuInfo> mLastCpuUsageSnapshot = null;
    private boolean mUseFreqForCpuUsage = false;
    private volatile boolean mIsBusy = false;

    ExecutorService mCalcExecutor = Executors.newFixedThreadPool(MAXIMUM_POOL_SIZE);


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            this.requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
        }

        Switch cpuBusySwitch = findViewById(R.id.cpu_busy);
        cpuBusySwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                if (isChecked) {
                    mIsBusy = true;
                    for (int i = 0; i < MAXIMUM_POOL_SIZE; i++) {
                        mCalcExecutor.execute(new Runnable() {
                            @Override
                            public void run() {
                                Random random = new Random(System.currentTimeMillis());
                                while (mIsBusy) {
                                    random.nextDouble();
                                }
                            }
                        });
                    }
                } else {
                    mIsBusy = false;
                }
            }
        });

        mCpuUsageTv = findViewById(R.id.cpu_use);

        new Thread(new Runnable() {
            @Override
            public void run() {

                while (true) {
                    final AllCoreFrequencyInfo fi = new AllCoreFrequencyInfo(CpuInfoCollector.calcCpuCoreCount());

                    int[] cpuUsages = null;
                    if (!mUseFreqForCpuUsage) {
                        final ArrayList<OneCpuInfo> currentCpuUsageSnapshot = CpuInfoCollector.takeCpuUsageSnapshot();
                        if (currentCpuUsageSnapshot != null) {
                            cpuUsages = MyUtil.calcCpuUsages(currentCpuUsageSnapshot, mLastCpuUsageSnapshot);
                            mLastCpuUsageSnapshot = currentCpuUsageSnapshot;
                        } else {
                            mUseFreqForCpuUsage = true;
                        }
                    }
                    if (cpuUsages == null) {
                        cpuUsages = MyUtil.calcCpuUsagesByCoreFrequencies(fi);
                    }
                    final StringBuilder cpuUsage = new StringBuilder();
                    for (int i = 0; i < cpuUsages.length; i++) {
                        cpuUsage.append("cpu");
                        cpuUsage.append(i);
                        cpuUsage.append(":");
                        cpuUsage.append(cpuUsages[i]);
                        cpuUsage.append("%");
                        cpuUsage.append("\n");
                    }
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            mCpuUsageTv.setText(cpuUsage);
                        }
                    });
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();


        findViewById(R.id.button_write30).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                File externalCacheDir = getExternalCacheDir();
                final File subDir = new File(externalCacheDir, "io");
                subDir.mkdirs();
                for (File f : subDir.listFiles()) {
                    f.delete();
                }
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        for (int i = 0; i < 30; i++) {
                            long begin = System.currentTimeMillis();

                            try {
                                DumpDataWriter.writeDumpData(subDir.getAbsolutePath() + "/io_" + i, 40 * 1024 * 1024);
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                            long end = System.currentTimeMillis() - begin;
                            Log.d("IO", "单线程30写入:" + i + "_" + end);

                        }
                    }
                }).start();

            }
        });
        findViewById(R.id.button2).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //单线程15写入15读取

                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        File externalCacheDir = getExternalCacheDir();
                        File subDir = new File(externalCacheDir, "io");
                        StopWatch.start();
                        for (int i = 0; i < 15; i++) {
                            long begin = System.currentTimeMillis();

                            try {
                                DumpDataWriter.readData(subDir.getAbsolutePath() + "/io_" + i);
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                            long end = System.currentTimeMillis() - begin;

                            Log.d("IO", "单线程15读取:" + i + "_" + end);

                        }
                        for (int i = 0; i < 15; i++) {
                            long begin = System.currentTimeMillis();

                            try {
                                DumpDataWriter.writeDumpData(subDir.getAbsolutePath() + "/iotest_" + System.currentTimeMillis(), 40 * 1024 * 1024);
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                            long end = System.currentTimeMillis() - begin;

                            Log.d("IO", "单线程15写入:" + i + "_" + end);

                        }
                        Log.d("IO", "单线程15写入15读取:" + StopWatch.stop());
                    }
                }).start();
            }
        });
        findViewById(R.id.button3).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //多线程15写入15读取

                File externalCacheDir = getExternalCacheDir();
                final File subDir = new File(externalCacheDir, "io");
                final CountDownLatch countDownLatch = new CountDownLatch(30);
                long allBegin = System.currentTimeMillis();

                for (int i = 0; i < 15; i++) {
                    final int index = i;
                    new Thread(new Runnable() {
                        @Override
                        public void run() {
                            long begin = System.currentTimeMillis();
                            try {
                                DumpDataWriter.readData(subDir.getAbsolutePath() + "/io_" + index);
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                            countDownLatch.countDown();

                            long end = System.currentTimeMillis() - begin;
                            Log.d("IO", "多线程15读取:" + index + "_" + end);

                        }
                    }).start();
                    new Thread(new Runnable() {
                        @Override
                        public void run() {
                            long begin = System.currentTimeMillis();

                            try {
                                DumpDataWriter.writeDumpData(subDir.getAbsolutePath() + "/iotest_" + index + "_" + System.currentTimeMillis(), 40 * 1024 * 1024);
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                            countDownLatch.countDown();
                            long end = System.currentTimeMillis() - begin;
                            Log.d("IO", "多线程15写入:" + index + "_" + end);
                        }
                    }).start();
                }
                try {
                    countDownLatch.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                long allEnd = System.currentTimeMillis() - allBegin;
                Log.d("IO", "allEnd:" + allEnd);

            }
        });

        findViewById(R.id.button4).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //NIO读写
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        File externalCacheDir = getExternalCacheDir();
                        File subDir = new File(externalCacheDir, "io");
                        long allBegin = System.currentTimeMillis();

                        for (int i = 0; i < 30; i++) {
                            long begin = System.currentTimeMillis();
                            StringBuilder stringBuilder = null;
                            try {
                                stringBuilder = DumpDataWriter.readDataNIO(subDir.getAbsolutePath() + "/io_" + i);
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                            long end = System.currentTimeMillis() - begin;

                            Log.d("IO", "NIO单线程30读取:" + i + "_" + end);

                        }
                        long allEnd = System.currentTimeMillis() - allBegin;
                        Log.d("IO", "allEnd:" + allEnd);

                    }
                }).start();

            }
        });
        findViewById(R.id.button5).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                //NIO读写
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        File externalCacheDir = getExternalCacheDir();
                        File subDir = new File(externalCacheDir, "io");
                        long allBegin = System.currentTimeMillis();

                        for (int i = 0; i < 30; i++) {
                            long begin = System.currentTimeMillis();

                            try {
                                DumpDataWriter.readData(subDir.getAbsolutePath() + "/io_" + i);
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                            long end = System.currentTimeMillis() - begin;

                            Log.d("IO", "阻塞IO单线程30读取:" + i + "_" + end);

                        }
                        long allEnd = System.currentTimeMillis() - allBegin;
                        Log.d("IO", "allEnd:" + allEnd);

                    }
                }).start();
            }
        });
        findViewById(R.id.button6).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                File externalCacheDir = getExternalCacheDir();
                File subDir = new File(externalCacheDir, "io");
                mmapFile(subDir.getAbsolutePath() + "/iommap_" + System.currentTimeMillis());
            }
        });
    }


    public native String stringFromJNI();

    public native void mmapFile(String filePath);
}
